package gc.analyze;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
	static final long SEC = (long) 1e7;
	static final long MAX_PAUSE = 1 * SEC;

	public static void main(String[] args) {
		List<TestResult> list = gather(new File("D:/Inforeach/Projects/TMS/trunk/gctests"), new ArrayList<TestResult>());
		Set<String> tst = new TreeSet<>();
		Map<String, Map<String, Map<String, TestResult>>> m0 = new TreeMap<>();
		for (TestResult r : list) {
			Map<String, Map<String, TestResult>> m1 = get(m0, r.getPrc());
			Map<String, TestResult> m2 = get(m1, r.getAlg());
			m2.put(r.getTst(), r);
			tst.add(r.getTst());
		}
		for (Map.Entry<String, Map<String, Map<String, TestResult>>> e0 : m0.entrySet()) {
			System.out.printf("%s\n", e0.getKey());
			System.out.printf("_");
			for (String hdr : tst) {
				System.out.printf("\tT%s", hdr);
			}
			System.out.printf("\n");
			System.out.printf("avg usage\n");
			for (Map.Entry<String, Map<String, TestResult>> e1 : e0.getValue().entrySet()) {
				System.out.printf("%s", e1.getKey());
				for (String hdr : tst) {
					TestResult tr = e1.getValue().get(hdr);
					if (tr != null) {
						System.out.printf("\t%7.3f", tr.getAvgUsage() * 100);
					} else {
						System.out.printf("\t");
					}
				}
				System.out.printf("\n");
			}
			System.out.printf("max usage\n");
			for (Map.Entry<String, Map<String, TestResult>> e1 : e0.getValue().entrySet()) {
				System.out.printf("%s", e1.getKey());
				for (String hdr : tst) {
					TestResult tr = e1.getValue().get(hdr);
					if (tr != null) {
						System.out.printf("\t%7.3f", tr.getMaxUsage());
					} else {
						System.out.printf("\t");
					}
				}
				System.out.printf("\n");
			}
			System.out.printf("histo pauses\n");
			for (Map.Entry<String, Map<String, TestResult>> e1 : e0.getValue().entrySet()) {
				for (Map.Entry<String, TestResult> e2 : e1.getValue().entrySet()) {
					System.out.printf("%s\t%s\n", e1.getKey(), e2.getKey());
					TestResult r = e2.getValue();
					int[] histo = r.getHisto();
					for (int i = 0; i < histo.length; ++i) {
						System.out.printf("\t%d", histo[i]);
					}
					System.out.printf("\n");
				}
				System.out.printf("\n");
			}
			System.out.printf("\n");
		}
	}

	static <K, L, V, M extends Map<K, Map<L, V>>> Map<L, V> get(M m, K k) {
		Map<L, V> n = m.get(k);
		if (n == null) {
			n = new TreeMap<L, V>();
			m.put(k,  n);
		}
		return n;
	}

	static <C extends Collection<? super TestResult>> C gather(File dir, C collection) {
		Pattern filename_pattern = Pattern.compile("gc-ELT(.*)\\.log");
		File dir0 = dir;
		for (File dir1 : dir0.listFiles()) {
			if (dir1.isDirectory()) {
				String alg = dir1.getName();
				File dir2 = new File(dir1, "res");
				if (dir2.isDirectory()) {
					for (File dir3 : dir2.listFiles()) {
						if (dir3.isDirectory()) {
							String tst = dir3.getName();
							for (File gclog : dir3.listFiles()) {
								if (gclog.isFile()) {
									Matcher matcher = filename_pattern.matcher(gclog.getName());
									if (matcher.matches()) {
										String prc = matcher.group(1);
										TestResult r = new TestResult(alg, tst, prc, gclog);
										try {
											long start = 360*SEC, end = 900*SEC;
											long[] raw_selected = Extract.subsequence(Extract.parse(gclog), start, end);
											long[] totals = Extract.totals(raw_selected);
											assert totals[2] == end - start : totals[2];
											long[] data = Smooth.smooth(raw_selected, MAX_PAUSE);
											int maxi = Smooth.maxi(data);
											double maxusage = data[maxi + 1] * 1e2 / MAX_PAUSE;
											double atmoment = (data[maxi] + start) / (double) SEC;
											r.setMaxUsage(maxusage, atmoment, totals[1] / (double) totals[2]);
											int[] histo = Extract.histo_stopped(raw_selected, 21, SEC / 2);
											r.setHisto(histo);
											collection.add(r);
										} catch (IOException exc) {
											System.out.printf("%s : %s\n", gclog, exc);
										}
									}
								}
							}
						}
					}
				}
			}
		}
		return collection;
	}

	static class TestResult {
		private final String alg_;
		private final String tst_;
		private final String prc_;
		private final File file_;

		private double maxusage_;
		private double atmoment_;
		private double avgusage_;
		private int[] histo_;

		public TestResult(String alg, String tst, String prc, File file) {
			alg_ = alg;
			tst_ = tst;
			prc_ = prc;
			file_ = file;
		}

		public String getAlg() {
			return alg_;
		}

		public String getTst() {
			return tst_;
		}

		public String getPrc() {
			return prc_;
		}

		public File getFile() {
			return file_;
		}

		public double getAvgUsage() {
			return avgusage_;
		}

		public double getMaxUsage() {
			return maxusage_;
		}

		public double getAtMoment() {
			return atmoment_;
		}

		public int[] getHisto() {
			return histo_;
		}

		public void setMaxUsage(double maxusage, double atmoment, double avgusage) {
			maxusage_ = maxusage;
			atmoment_ = atmoment;
			avgusage_ = avgusage;
		}

		public void setHisto(int[] histo) {
			histo_ = histo;
		}
	}
}
